/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.exception.ServiceException;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.core.utils.StreamUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.core.utils.file.FileUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.common.oss.constant.OssConstant;
import com.comac.ins.common.oss.core.OssClient;
import com.comac.ins.common.oss.entity.UploadResult;
import com.comac.ins.common.oss.enumd.AccessPolicyType;
import com.comac.ins.common.oss.factory.OssFactory;
import com.comac.ins.isfd.domain.IsfdModelGeneralPreprocess;
import com.comac.ins.isfd.domain.bo.IsfdModelGeneralPreprocessBo;
import com.comac.ins.isfd.domain.vo.IsfdMeshModelStructureDefinitionVo;
import com.comac.ins.isfd.domain.vo.IsfdModelGeneralPreprocessVo;
import com.comac.ins.isfd.domain.vo.IsfdModelManagementRenderingResultVo;
import com.comac.ins.isfd.mapper.IsfdModelGeneralPreprocessMapper;
import com.comac.ins.isfd.rpc.xuelang.XueLangRpcUtils;
import com.comac.ins.isfd.rpc.xuelang.bo.XueLangRenderBo;
import com.comac.ins.isfd.rpc.xuelang.bo.XueLangRenderExtraBo;
import com.comac.ins.isfd.rpc.xuelang.constants.enums.XueLangRenderFileTypeEnum;
import com.comac.ins.isfd.service.IIsfdCollectBatchHistoryService;
import com.comac.ins.isfd.service.IIsfdMeshModelStructureDefinitionService;
import com.comac.ins.isfd.service.IIsfdModelGeneralPreprocessService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 结构分析通用前处理模型库Service业务层处理
 *
 * @author Lion Li
 * @date 2025-08-29
 */
@RequiredArgsConstructor
@Service
public class IsfdModelGeneralPreprocessServiceImpl implements IIsfdModelGeneralPreprocessService {

    @Autowired
    private IsfdModelGeneralPreprocessMapper baseMapper;

    @Autowired
    private IIsfdCollectBatchHistoryService iIsfdCollectBatchHistoryService;

    @Autowired
    private IIsfdMeshModelStructureDefinitionService iIsfdMeshModelStructureDefinitionService;

    @Autowired
    private XueLangRpcUtils xueLangRpcUtils;

    @Value("${evn.evnType}")
    private String evnType;

    /**
     * 分页查询结构分析通用前处理模型库列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 结构分析通用前处理模型库分页列表
     */
    @Override
    public TableDataInfo<IsfdModelGeneralPreprocessVo> queryPageList(IsfdModelGeneralPreprocessBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<IsfdModelGeneralPreprocess> lqw = buildQueryWrapper(bo);
        Page<IsfdModelGeneralPreprocessVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<IsfdModelGeneralPreprocessVo> filterResult;
        if (evnType.equals("red")) {
            filterResult = StreamUtils.toList(result.getRecords(), this::signUrl);
        } else {
            filterResult = StreamUtils.toList(result.getRecords(), this::matchingUrl);
        }
        result.setRecords(filterResult);
        return TableDataInfo.build(result);
    }

    private LambdaQueryWrapper<IsfdModelGeneralPreprocess> buildQueryWrapper(IsfdModelGeneralPreprocessBo bo) {
        LambdaQueryWrapper<IsfdModelGeneralPreprocess> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getFileName()), IsfdModelGeneralPreprocess::getFileName, bo.getFileName());
        lqw.eq(StringUtils.isNotBlank(bo.getModelNumber()), IsfdModelGeneralPreprocess::getModelNumber, bo.getModelNumber());
        lqw.like(StringUtils.isNotBlank(bo.getBatchNumber()), IsfdModelGeneralPreprocess::getBatchNumber, bo.getBatchNumber());
        lqw.like(StringUtils.isNotBlank(bo.getSectionNumber()), IsfdModelGeneralPreprocess::getSectionNumber, bo.getSectionNumber());
        lqw.like(StringUtils.isNotBlank(bo.getSectionName()), IsfdModelGeneralPreprocess::getSectionName, bo.getSectionName());
        lqw.orderByDesc(IsfdModelGeneralPreprocess::getCreateTime);
        return lqw;
    }

    /**
     * 新增结构分析通用前处理模型库
     *
     * @param bo 结构分析通用前处理模型库
     * @return 是否新增成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(IsfdModelGeneralPreprocessBo bo) {
        // 校验入参
        validEntityBeforeSave(bo);
        IsfdModelGeneralPreprocess add = MapstructUtils.convert(bo, IsfdModelGeneralPreprocess.class);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    @Override
    public Boolean save(MultipartFile file, IsfdModelGeneralPreprocessBo bo) {
        // 上传文件至OSS
        String originalFileName = new File(file.getOriginalFilename()).getName();
        String fileName = originalFileName; // 带后缀
        String suffix = ""; // 后缀，带点

        int dotIndex = originalFileName.lastIndexOf('.');
        if (dotIndex >= 0) {
            suffix = originalFileName.substring(dotIndex); // 只取后缀
        }

        OssClient storage = OssFactory.instance(OssConstant.PREPROCESSING_CONFIG_KEY);
        UploadResult uploadResult;
        try {
            uploadResult = storage.uploadSuffix(file.getBytes(), suffix);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        }
        bo.setFileName(fileName);
        bo.setUrl(uploadResult.getUrl());
        bo.setFilePath(uploadResult.getFilename());
        // 保存模型信息
        return insertByBo(bo);
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(IsfdModelGeneralPreprocessBo entity) {
        // 检查modelNumber
        String modelNumber = entity.getModelNumber();
        IsfdMeshModelStructureDefinitionVo modelIndex = iIsfdMeshModelStructureDefinitionService.queryOneByQueryIndex(modelNumber, null, null);
        if (modelIndex == null) {
            throw new BaseException("机型" + modelNumber + " 未定义");
        }
        entity.setModelName(modelIndex.getName());

        // 检查 sectionNumber
        String sectionNumber = entity.getSectionNumber();
        String[] sectionNumbers = sectionNumber.split(",");
        List<String> sectionNames = new ArrayList<>();
        for (String singleSectionNumber : sectionNumbers) {
            IsfdMeshModelStructureDefinitionVo sectionVo = iIsfdMeshModelStructureDefinitionService.queryOneByQueryIndex(modelNumber, singleSectionNumber, null);
            if (sectionVo == null) {
                throw new BaseException("部段" + sectionNumber + " 未定义");
            }
            sectionNames.add(sectionVo.getName());
        }

        // 逗号隔开的字符串
        String sectionNameStr = String.join(",", sectionNames);
        entity.setSectionName(sectionNameStr);

        // 处理batchNumber
        String batchNumber = entity.getBatchNumber();
        entity.setBatchNumber(batchNumber);
        entity.setBatchName(batchNumber);
        iIsfdCollectBatchHistoryService.save(modelNumber, batchNumber);
    }

    /**
     * 校验并批量删除结构分析通用前处理模型库信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        List<IsfdModelGeneralPreprocess> pos = baseMapper.selectBatchIds(ids);
        for (IsfdModelGeneralPreprocess po : pos) {
//            deleteFileOnOss(po);
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    private void deleteFileOnOss(IsfdModelGeneralPreprocess po) {
        String url = po.getUrl();
        if (StringUtils.isEmpty(url)) {
            return;
        }
        OssClient storage = OssFactory.instance();
        storage.delete(url);
    }

    private IsfdModelGeneralPreprocessVo matchingUrl(IsfdModelGeneralPreprocessVo modelVo) {
        OssClient storage = OssFactory.instance();
        // 仅修改桶类型为 private 的URL，临时URL时长为120s
        if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) {
            modelVo.setUrl(storage.getPrivateUrl(modelVo.getFileName(), 120));
        }
        return modelVo;
    }

    private IsfdModelGeneralPreprocessVo signUrl(IsfdModelGeneralPreprocessVo modelVo) {
        OssClient storage = OssFactory.instance(OssConstant.PREPROCESSING_CONFIG_KEY);
        modelVo.setUrl(storage.OssSignedUrl(modelVo.getFilePath()));
        return modelVo;
    }

    @Override
    public void download(Long modelId, HttpServletResponse response) throws IOException {
        IsfdModelGeneralPreprocessVo vo = baseMapper.selectVoById(modelId);
        if (ObjectUtil.isNull(vo)) {
            throw new ServiceException("文件数据不存在!");
        }
        FileUtils.setAttachmentResponseHeader(response, vo.getFileName());
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
        OssClient storage = OssFactory.instance(OssConstant.PREPROCESSING_CONFIG_KEY);
        long contentLength = storage.download(vo.getFilePath(), response.getOutputStream());
        response.setContentLengthLong(contentLength);
    }

    @Override
    public IsfdModelManagementRenderingResultVo loadModel(Long id) {
        IsfdModelGeneralPreprocessVo isfdModelGeneralPreprocessVo = baseMapper.selectVoById(id);
        if (isfdModelGeneralPreprocessVo == null) {
            throw new BaseException("精细模型管理模型库不存在，请确认后重试！");
        }
        String url = isfdModelGeneralPreprocessVo.getUrl();
        if (StringUtils.isBlank(url)) {
            throw new BaseException("精细模型管理模型库未上传文件，请确认后重试！");
        }
        String fileName = isfdModelGeneralPreprocessVo.getFileName();
        XueLangRenderFileTypeEnum xueLangRenderFileTypeEnum = XueLangRenderFileTypeEnum.checkFileNameSuffix(fileName);
        if (xueLangRenderFileTypeEnum == null) {
            throw new BaseException("精细模型管理模型库文件格式不正确，请确认是否是zip或者bdf格式！");
        }

        // url加签
        IsfdModelGeneralPreprocessVo targetVo = null;
        if (evnType.equals("red")) {
            targetVo = this.signUrl(isfdModelGeneralPreprocessVo);
        } else {
            targetVo = this.matchingUrl(isfdModelGeneralPreprocessVo);
        }

        XueLangRenderBo xueLangRenderBo = new XueLangRenderBo();
        XueLangRenderExtraBo extraBo = new XueLangRenderExtraBo();
        xueLangRenderBo.setUrl(targetVo.getUrl());
        xueLangRenderBo.setType(XueLangRenderFileTypeEnum.BDF.getValue());
        if(xueLangRenderFileTypeEnum.getValue().endsWith(XueLangRenderFileTypeEnum.ZIP.getValue())){
            xueLangRenderBo.setEntryFile(isfdModelGeneralPreprocessVo.getIndexFileName());
            extraBo.setTaskName(isfdModelGeneralPreprocessVo.getModeName());
        }
        extraBo.setModelNumber(isfdModelGeneralPreprocessVo.getModelNumber());
        extraBo.setModelName(isfdModelGeneralPreprocessVo.getModelName());
        extraBo.setSectionNumbers(isfdModelGeneralPreprocessVo.getSectionNumber());
        extraBo.setSectionNames(isfdModelGeneralPreprocessVo.getSectionName());
        extraBo.setBatchNumber(isfdModelGeneralPreprocessVo.getBatchNumber());
        extraBo.setBatchName(isfdModelGeneralPreprocessVo.getBatchName());
        xueLangRenderBo.setExtra(extraBo);
        //调用第三方团队接口获取renderUrl
        String renderUrl = xueLangRpcUtils.render(xueLangRenderBo);
//        String renderUrl = "www.baidu.com";
        IsfdModelManagementRenderingResultVo result = new IsfdModelManagementRenderingResultVo();
        result.setRenderUrl(renderUrl);
        return result;
    }
}
